package com.liziyi0914.morearmor.effect;

import com.liziyi0914.morearmor.Utils;
import com.liziyi0914.morearmor.event.Listener;
import com.liziyi0914.morearmor.event.entity.EntityClickEvent;
import com.liziyi0914.morearmor.event.entity.EntityMoveEvent;
import net.minecraft.block.BlockState;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Items;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Heightmap;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

public class EnderEyeEffect extends AbstractEffect {

    private final Map<UUID, Long> cd = new LinkedHashMap<>();

    @Override
    public Predicate<LivingEntity> predicateArmor() {
        return Utils.hasItemArmor(Items.ENDER_EYE).or(Utils.hasItemArmor(Items.ENDER_PEARL));
    }

    @Listener
    public void onMove(EntityMoveEvent e) {
        if (!predicateArmor().test(e.getEntity())) return;
        final ServerWorld world = e.getWorld();
        final BlockState blockState = world.getBlockState(e.getTo());
        if (blockState.getFluidState().getFluid() == Fluids.WATER || blockState.getFluidState().getFluid() == Fluids.FLOWING_WATER) {
            LivingEntity entity = e.getEntity();
            long current = System.currentTimeMillis();
            long lastTp = cd.getOrDefault(entity.getUuid(), 0L);
            if (current - lastTp >= TimeUnit.SECONDS.toMillis(10) && entity.isTouchingWaterOrRain()) {
                lastTp = current;
                cd.put(entity.getUuid(), lastTp);
                e.getEntity().world.playSound(null, e.getFrom(), SoundEvents.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
                teleport(entity, 10);//todo 如果玩家已经在水里了player moved wrongly!
                e.setCanceled(true);
            }
        }
    }

    @Listener
    public void onInteractItem(EntityClickEvent e) {
        if (!e.isLeft()) return;
        if (!predicateArmor().test(e.getEntity())) return;
        LivingEntity entity = e.getEntity();
        long current = System.currentTimeMillis();
        long lastTp = cd.getOrDefault(entity.getUuid(), 0L);
        if (current - lastTp >= TimeUnit.SECONDS.toMillis(20)) {
            lastTp = current;
            cd.put(entity.getUuid(), lastTp);
            e.getEntity().world.playSound(null, entity.getBlockPos(), SoundEvents.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
            teleport(e.getEntity(), 15);
        }
    }

    private void teleport(LivingEntity entity, int r) {
        final BlockPos location = getLocation(entity, r);
        entity.teleport(location.getX(), location.getY(), location.getZ());
    }

    private BlockPos getLocation(LivingEntity entity, int r) {
        Random rnd = new Random();
        double x = entity.getX() + rnd.nextInt(r * 2) - r;
        double z = entity.getZ() + rnd.nextInt(r * 2) - r;
        double y = entity.getEntityWorld().getTopY(Heightmap.Type.MOTION_BLOCKING, (int) x, (int) z);
        return new BlockPos(x, y, z);
    }
}
